package com.itheima.consumer.controller;


import com.google.gson.Gson;
import com.itheima.consumer.util.POIUtils;
import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;


@RestController
@RequestMapping("/consumer")
@Slf4j
@DefaultProperties(defaultFallback = "defaultFallback")
public class ConsumerController {
    @Autowired
    public RestTemplate restTemplate;
    //服务获取工具类
    @Autowired
    public DiscoveryClient discoveryClient;

    /**
     * 使用了Eureka服务调用：直接访问服务提供方的id不再是默认host
     *
     * @param id
     * @return
     */
    @GetMapping({"/{id}"})
    @HystrixCommand(fallbackMethod = "queryByIdFallback")
//    @HystrixCommand
    public String queryById(@PathVariable Long id) {
       /* String url = "http://localhost:9091/user/" + id;
        List<ServiceInstance> instanceList = discoveryClient.getInstances("user-service");
        ServiceInstance serviceInstance = instanceList.get(0);
        url = "http://"+serviceInstance.getHost()+":"+serviceInstance.getPort()+"/user/"+id;
        不再手动获取ip和端口，而是直接通过服务名称调用(开启负载均衡后，直接通过服务名称获取对应的访问路径和端口)
        */
        if (id == 1) {
            throw new RuntimeException("服务器繁忙中----稍后访问");
        }
        String url = "http://user-service/user/" + id;
        String user = restTemplate.getForObject(url, String.class);
        /**
         * 为了保证：
         * 因为熔断的降级逻辑方法必须跟正常逻辑方法保证：相同的参数列表和返回值声明。
         * 失败逻辑中返回User对象没有太大意义，一般会返回友好提示。所以把queryById的方法改造为返回String，
         * 反正也是Json数据。这样失败逻辑中返回一个错误说明，会比较方便。
         */
        return user;
    }

    //当类上或者方法上均有熔断的降级逻辑方法时，方法上的先生效  就近原则
    public String queryByIdFallback(Long id) {
//        log.error("查询用户信息失败。id：{}", id);
        return "对不起，网络太拥挤！";
    }

    public String defaultFallback() {
        return "默认提示：对不起，网络太拥挤了！";
    }

    @RequestMapping("/selectOutLine")
    public List<String> selectOutLine(@RequestParam("uploadFile") MultipartFile file, String itcastUrl) throws IOException {
        //通过用户输入的URL获取返回数据,返回的json字符串
        ResponseEntity<String> data = restTemplate.getForEntity(itcastUrl, String.class);
        //获取响应体重的body信息
        String dataBody = data.getBody();
        Gson gson = new Gson();
        //封装为一个map对象
        Map fromJson = gson.fromJson(dataBody, Map.class);
        List<Map<String,String>> onlineUsers = (List<Map<String, String>>) fromJson.get("onlineUsers");
        //创建一个集合用于缓存在线人员的姓名
        ArrayList<String> arrayList = new ArrayList<String>();
        for (Map<String, String> onlineUser : onlineUsers) {
            String name = onlineUser.get("name");
            arrayList.add(name);
        }
        //解析文档
        List<String[]> list = POIUtils.readExcel(file);
        ArrayList<String> arrayList1 = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            String name = list.get(i)[0];
            arrayList.add(name);
        }
        arrayList1.removeAll(arrayList);
        return arrayList1;
    }
}
